package com.ruoyi.common.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.SimplifiedObjectMeta;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.time.LocalDate;
import java.util.Date;
import java.util.HashMap;

/*
 * https://lwzx.oss-cn-hangzhou.aliyuncs.com/
 * */
@Slf4j
public class OSSUtils {
    //    static Logger logger = Logger.getLogger(HelloOSS.class);
    // endpoint是访问OSS的域名。如果您已经在OSS的控制台上 创建了Bucket，请在控制台上查看域名。
    // 如果您还没有创建Bucket，endpoint选择请参看文档中心的“开发人员指南 > 基本概念 > 访问域名”，
    // 链接地址是：https://help.aliyun.com/document_detail/oss/user_guide/oss_concept/endpoint.html?spm=5176.docoss/user_guide/endpoint_region
    // endpoint的格式形如“http://oss-cn-hangzhou.aliyuncs.com/”，注意http://后不带bucket名称，
    // 比如“http://bucket-name.oss-cn-hangzhou.aliyuncs.com”，是错误的endpoint，请去掉其中的“bucket-name”。
    private static String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
    private static String url = "https://lwzx.oss-cn-hangzhou.aliyuncs.com/";

    // accessKeyId和accessKeySecret是OSS的访问密钥，您可以在控制台上创建和查看，
    // 创建和查看访问密钥的链接地址是：https://ak-console.aliyun.com/#/。
    // 注意：accessKeyId和accessKeySecret前后都没有空格，从控制台复制时请检查并去除多余的空格。
    private static String accessKeyId = "LTAIrgZ75N21kuEJ";
    private static String accessKeySecret = "A8dr0S5oNwjtbvmginUsEDojb3Bsjx";

    // Bucket用来管理所存储Object的存储空间，详细描述请参看“开发人员指南 > 基本概念 > OSS基本概念介绍”。
    // Bucket命名规范如下：只能包括小写字母，数字和短横线（-），必须以小写字母或者数字开头，长度必须在3-63字节之间。
    private static String bucketName = "lwzx";

    // Object是OSS存储数据的基本单元，称为OSS的对象，也被称为OSS的文件。详细描述请参看“开发人员指南 > 基本概念 > OSS基本概念介绍”。
    // Object命名规范如下：使用UTF-8编码，长度必须在1-1023字节之间，不能以“/”或者“\”字符开头。
    private static String firstKey = "test-key";

    public static String savePdf(String fileKey, InputStream inputStream) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, fileKey, inputStream);
        ossClient.setObjectAcl(bucketName, fileKey, CannedAccessControlList.PublicRead);
        ossClient.shutdown();
        return fileKey;
    }

    public static String uploadImage(String prefix, MultipartFile file) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String fileKey = prefix + "/" + DateUtils.dateTimeNow() + file.getOriginalFilename();
        ossClient.putObject(bucketName, fileKey, inputStream);
        ossClient.setObjectAcl(bucketName, fileKey, CannedAccessControlList.PublicRead);
        ossClient.shutdown();
        return url + fileKey;
    }

    public static void downLoadFile(String fileName, HttpServletResponse response) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, fileName, HttpMethod.GET);
        // 设置过期时间。
        request.setExpiration(expiration);
        // 生成签名URL（HTTP GET请求）。
        URL signedUrl = ossClient.generatePresignedUrl(request);
        // 使用签名URL发送请求。
        fileName = fileName.replace("/", "");
        OSSObject ossObject = ossClient.getObject(signedUrl, new HashMap<>());
        try (InputStream fis = ossObject.getObjectContent();
             OutputStream fos = response.getOutputStream();
             BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            response.setContentType("application/octet-stream; charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment; fileName=" + new String("兰湾足行加盟商协议.pdf".getBytes("UTF-8"), "iso-8859-1"));
            int bytesRead = 0;
            byte[] buffer = new byte[1024];
            while ((bytesRead = fis.read(buffer, 0, 1024)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            bos.flush();
        } catch (Exception e) {
            log.error("**********************OssClient-->download throw Exception.name:{},code:{}**********************");
        }
        ossClient.shutdown();
    }

    /*
     * ********************************************新的文件空间********************************************
     * */
    public static String SERVER_URL = "https://api.gdlwzn.com/back/file/";
    //    public static String SERVER_URL = "http://localhost:80/back/file/";
    public static String PRE_URL = "https://lwzx.oss-cn-beijing.aliyuncs.com/";   // 定义新路径，新文件将统一存放在此
    public static String VIDEO_PACKAGE = "video/";   // 存放视频文件的地方
    public static String IMAGE_PACKAGE = "image/";   // 存放图片的地方
    public static String OTHERS_PACKAGE = "others/";   // 存放其他文件的地方
    public static String BUCKET_NAME = "lwzx";   // 存放其他文件的地方
    private static String END_POINT = "http://oss-cn-beijing.aliyuncs.com";

    /**
     * 上传图片到oss的lwzn-wxsw仓库，并返回相对路径
     *
     * @param file
     * @return
     */
    public static String uploadImageFile(MultipartFile file) {
        OSSClient ossClient = new OSSClient(END_POINT, accessKeyId, accessKeySecret);
        String fileKey = getPath(file.getOriginalFilename());        // 直接使用原文件名

        try {
            InputStream inputStream = file.getInputStream();
            ossClient.putObject(BUCKET_NAME, fileKey, inputStream);
            log.info("文件：" + fileKey + "存入OSS成功。");
            ossClient.setObjectAcl(BUCKET_NAME, fileKey, CannedAccessControlList.Default);
        } catch (OSSException oe) {
            oe.printStackTrace();
        } catch (ClientException ce) {
            ce.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ossClient.shutdown();
        }
        return fileKey;
    }

    /**
     * 拼接文件路径，判断这个文件是图片/视频/其他文件。
     *
     * @param fileKey 文件名，例如：image/2019/12/123.jpg
     * @return https://lwzn-wxsw.oss-cn-beijing.aliyuncs.com/image/2019/12/123.jpg
     */
    public static URL getUrl(String fileKey) {
        if (StringUtils.isEmpty(fileKey)) {
            return null;
        }
        fileKey = PRE_URL + fileKey;
        URL url = null;
        try {
            url = new URL(fileKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return url;
    }

    /**
     * 拼接文件路径，判断这个文件是图片/视频/其他文件。
     *
     * @param fileName 文件名，例如：123.jpg
     * @return image/2019/11/123.jpg
     */
    public static String getPath(String fileName) {
        if (StringUtils.isEmpty(fileName)) {
            return null;
        }
        String packageName = fileSwitch(fileName.substring(fileName.lastIndexOf(".") + 1));
        LocalDate date = LocalDate.now();
        String fileKey = "";
        fileKey = packageName + date.getYear() + "/" + date.getMonthValue() + "/" + fileName;
        return fileKey;
    }

    public static String fileSwitch(String postfix) {
        switch (postfix.toLowerCase()) {
            case "jpg":
                return IMAGE_PACKAGE;
            case "gif":
                return IMAGE_PACKAGE;
            case "png":
                return IMAGE_PACKAGE;
            case "bmp":
                return IMAGE_PACKAGE;

            case "avi":
                return VIDEO_PACKAGE;
            case "mov":
                return VIDEO_PACKAGE;
            case "rmvb":
                return VIDEO_PACKAGE;
            case "flv":
                return VIDEO_PACKAGE;
            case "mp4":
                return VIDEO_PACKAGE;

            default:
                return OTHERS_PACKAGE;
        }
    }

    /**
     * 获取视频文件大小
     * 旧视频地址为全路径减前缀
     * 新地址为全路径, OSSClient参数中的END_POINT也不同
     *
     * @param videoUrl
     * @return
     */
    public static String getVideoSize(String videoUrl) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        String size = "";
        SimplifiedObjectMeta objectMeta;
        try {
            if (videoUrl.contains(url)) {                               // 如果包含旧前缀的
                firstKey = videoUrl.replace(url, "");
                objectMeta = ossClient.getSimplifiedObjectMeta(bucketName, firstKey);
            } else if (videoUrl.contains(PRE_URL)) {                    // 如果包含新前缀的
                firstKey = videoUrl.replace(PRE_URL, "");
                ossClient = new OSSClient(END_POINT, accessKeyId, accessKeySecret);
                objectMeta = ossClient.getSimplifiedObjectMeta(BUCKET_NAME, firstKey);
            } else {                                                     // 如果不包含前缀的
                firstKey = videoUrl;
                objectMeta = ossClient.getSimplifiedObjectMeta(bucketName, firstKey);
            }
            size = objectMeta.getSize() + "";
        } catch (OSSException oe) {
            oe.printStackTrace();
        } catch (ClientException ce) {
            ce.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ossClient.shutdown();
        }
        return size;
    }

    /**
     * 获取视频图片外网URL
     * 兼容新旧两个版本的地址数据
     *
     * @param fileKey
     * @return
     */
    public static URL generatePresignedUrl(String fileKey) {
        if (StringUtils.isEmpty(fileKey)) {
            return null;
        }
        URL urls = null;
        try {
            if (fileKey.contains("https://lwzn-wxsw")) {        // 如果这个字符串链接包含前缀，那就直接返回
                urls = new URL(fileKey);
            } else {
                fileKey = url + fileKey;                         // 如果不包含，则表示是旧数据，需要补前缀
                urls = new URL(fileKey);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return urls;
    }

    public static void upPosterImage(InputStream inputStream, String fileKey) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        try {
            ossClient.putObject(bucketName, fileKey, inputStream);
            log.info("Object：" + fileKey + "存入OSS成功。");
            ossClient.setObjectAcl(bucketName, fileKey, CannedAccessControlList.Default);
        } finally {
            ossClient.shutdown();
        }
    }

    public static void main(String[] args) {
        System.out.println(getPath("123.jpg"));
        System.out.println(getUrl("123.jpg"));
        System.out.println(getVideoSize(getUrl("others/2019/12/7FXbtzGYGr.mp4").toString()));

        System.out.println(getVideoSize("video/model/pic/5eb6623e-3b37-4516-81f8-ac6b15c068f8.jpg"));
        System.out.println(getVideoSize(url + "video/model/pic/5eb6623e-3b37-4516-81f8-ac6b15c068f8.jpg"));
        System.out.println(getVideoSize("https://lwzn-wxsw.oss-cn-beijing.aliyuncs.com/image/2019/12/TIM图片20191202091449.jpg"));

    }
}

